<?php

class DataList
{
    private $id = 'datalist';
    private $sql = null;
    private $sessKey = null;
    private $url = null;
    private $total = 0;
    private $nowPage = 1;
    private $data = null;
    private $page = null;
    private $config = [
        'field' => '*',
        'table' => '',
        'where' => '',
        'group' => '',
        'having' => '',
        'order' => '',
        'ul.class' => 'pagination',
        'div.class' => 'row text-center',
        'total.show' => true,
    ];

    public function parseSql($sql)
    {
        if ($sql == null)
            return false;

        $sql = trim($sql);
        if (stripos($sql, 'select ') === false) {
            $this->config['table'] = $sql;
            return true;
        }

        $pos = stripos($sql, ' from ');
        if ($pos === false || stripos($sql, ' limit ') !== false)
            return false;

        $this->sql = $sql;

        $this->total = sqlCol('SELECT count(*) '.substr($sql, $pos)) ?? 0;

        return true;
    }

    public function getNowPage()
    {
        if (isset($_GET['page']) && $_GET['page'] != 0) {
            $nowPage = $_GET['page'];
        } else {
            $nowPage = 1;
        }
        return $nowPage;
    }

    public function __construct($sql = null, $id = null, $config = [])
    {
        $this->parseSql($sql);

        if ($id !== null)
            $this->id = $id;

        $this->sessKey = sha1($this->id.$sql);
        session($this->id.'.url', $_SERVER['REQUEST_URI']);

        //获取一页多少条记录
        $this->config['page.size'] = config('paginate.list_rows');
        //获取总共显示多少页
        $this->config['page.roll'] = config('paginate.roll');

        $this->config = $config + $this->config;
        $this->nowPage = $this->getNowPage();
    }

    static public function obj($sql = null, $id = null, $config = [])
    {
        return new DataList($sql, $id, $config);
    }

    public function table($val)
    {
        return $this->set('table', $val);
    }

    public function field($val)
    {
        return $this->set('field', $val);
    }

    public function where($val)
    {
        return $this->set('where', ' WHERE '.$val);
    }

    public function group($val)
    {
        return $this->set('group', ' GROUP BY '.$val);
    }

    public function having($val)
    {
        return $this->set('having', ' HAVING '.$val);
    }

    public function order($val)
    {
        return $this->set('order', 'ORDER BY '.$val);
    }

    public function __get($name)
    {
        return $this->$name;
    }

    public function set($name, $value = null, $append = false)
    {
        if (is_array($name)) {
            $this->config = $name + $this->config;
        } else if ($value !== null) {
            if ($append)
                $this->config[$name] .= $value;
            else
                $this->config[$name] = $value;
        } else if (isset($this->config[$name])) {
            unset($this->config[$name]);
        }

        return $this;
    }

    public function get($name = null)
    {
        if ($name === null)
            return $this->config;

        if (isset($this->config[$name]))
            return $this->config[$name];

        return null;
    }

    private function getLimit($size = null)
    {
        $pageSize = $size ?? $this->config['page.size'];
        $this->config['page.size'] = $pageSize;
        $pageStart = ($this->nowPage - 1) * $pageSize;
        return ' LIMIT '.$pageStart.', '.$pageSize;
    }

    public function fetch($size = null, $roll = null)
    {
        if ($this->sql !== null) {
            $sql = $this->sql;
        } else {
            $sql = sprintf(' FROM %s %s %s %s %s',
                    $this->config['table'],
                    $this->config['where'],
                    $this->config['group'],
                    $this->config['having'],
                    $this->config['order']
                );
            $this->total = sqlCol('SELECT count(*) '.$sql) ?? 0;
            // dump('<div style="height=120px"></div>');
            // dump($sql);
            $sql = 'SELECT '.$this->config['field'].$sql;
        }
        //必须先获取分页, 确定nowPage的值才能获取Limit
        $this->page = $this->pageFetch($size, $roll);
        $limit = $this->getLimit($size);
        $this->data = sqlAll($sql.$limit);

        return $this;
    }

    public function getUrl()
    {
        $query = explode('&', $_SERVER['QUERY_STRING']);
        $string = "";
        foreach ($query as $val) {
            if (!strncasecmp($val, 'data_id=', 8)
                    ||!strncasecmp($val, "page=", 5))
                continue;
            $string .= $val.'&';
        }
        $string === "&" && $string = "";
        $url = $_SERVER['PHP_SELF']."?".$string."data_id=".$this->id;
        if (isset($this->config['url.param']))
            $url .= '&'.$this->config['url.param'];
        return $url;
    }

    private function pageLink($page, $txt, $class)
    {
        $url = $this->getUrl().'&page='.$page;

        return '<li class='.$class.'>'.html_link($url, "#".$this->id, 'a', $txt).'</li>';
    }

    private function pageFetch($pageSize = null, $pageRoll = null)
    {
        if ($this->total == 0)
            return "";

        $pageSize = $pageSize ?? $this->config['page.size'];
        $pageRoll = $pageRoll ?? $this->config['page.roll'];
        //获取总页数
        $totalPage = ceil($this->total / $pageSize);

        //获取页栏中间页
        $rollMid = floor($pageRoll / 2);
        $rollMidCeil = ceil($rollMid);

        $this->nowPage < 1 && $this->nowPage = 1;
        $this->nowPage > $totalPage && $this->nowPage = $totalPage;

        //上一页
        $up = "";
        $up_row = $this->nowPage - 1;
        if ($up_row > 0 && $totalPage > $pageRoll) {
            $up = $this->pageLink($up_row, '上一页', 'page-prev');
        }

        //下一页
        $down = "";
        $down_row = $this->nowPage + 1;
        if ($down_row <= $totalPage && $totalPage > $pageRoll) {
            $down = $this->pageLink($down_row, '下一页', 'page-next');
        }

        //首页
        $first = "";
        if ($totalPage > $pageRoll && $this->nowPage > $rollMid + 1) {
            $first = $this->pageLink(1, 1, 'page-first');
        }

        //尾页
        $last = "";
        if ($totalPage > $pageRoll
                && $this->nowPage + $rollMid < $totalPage) {
            $last = $this->pageLink($totalPage, $totalPage, 'page-last');
        }

        //显示数字链接页

        $link = "";
        if ($totalPage > 1) {
            if ($this->nowPage <= $rollMid || $totalPage <= $pageRoll)
                $start = 1;
            else if ($totalPage >= $pageRoll
                        && $this->nowPage + $rollMid > $totalPage)
                $start = $totalPage - $pageRoll + 1;
            else
                $start = $this->nowPage - $rollMid;

            $end = $totalPage <= $pageRoll ? $totalPage
                                          : $start + $pageRoll - 1;
            for ($i = $start; $i <= $end; ++$i) {
                if ($i == $this->nowPage)
                    $link .= $this->pageLink($i, $i, 'active');
                else
                    $link .= $this->pageLink($i, $i, 'page-num');
            }
        }

        $html = '<div class="'.$this->config['div.class'].'">';
        $html .= '<ul class="'.$this->config['ul.class'].'">';
        $html .= $first.$up.$link.$down.$last;

        if ($this->config['total.show']) {
            $html .= '<li><a href="javascript:void(0)">共&nbsp;';
            $html .= '<span class="page-total">'.$this->total.'</span>';
            $html .= '&nbsp;条记录</a></li>';
        }

        $html .= '</ul></div>';

        return $html;
    }
}
